package com.lolxxs.aop;

import com.lolxxs.annotation.MyCacheEvict;
import com.lolxxs.annotation.MyCachePut;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Component
@Aspect
public class CacheEvictAspact {
    @Autowired
    private CacheManager cacheManager;

    @Pointcut("@annotation(com.lolxxs.annotation.MyCacheEvict)")
    public void pointcut() {

    }

    @Around("pointcut()")
    public Object round(ProceedingJoinPoint point) {
        System.out.println("代理类运行3");
        // 获取被代理类的签名
        Signature signature = point.getSignature();
        // 获取被代理类对象
        Object target = point.getTarget();
        // 获取被代理类class对象
        Class declaringType = signature.getDeclaringType();
        // 获取类中的方法
        Method[] methods = declaringType.getMethods();
        Method targetMethod = null;
        for (Method method : methods) {
            // 如果该方法名和AOP代理切入点方法名相同

            if (method.getName().equals(signature.getName())) {
                targetMethod = method;
                break;
            }
        }
        Cache cache = null;
        Object arg = null;
        if (targetMethod != null) {
            MyCacheEvict myCacheable = (MyCacheEvict)targetMethod.getAnnotation(MyCacheEvict.class);
            if (myCacheable != null) {
                // 获取缓存名
                String value = myCacheable.value();
                // 获取缓存中的键，其实是参数名
                String key = myCacheable.key();

                cache = cacheManager.getCache(value);
                // 获取方法的参数列表
                Parameter[] parameters = targetMethod.getParameters();
                Object[] args = point.getArgs();
                LocalVariableTableParameterNameDiscoverer localVariableTableParameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();

                // 获取方法名称列表
                String[] parameterNames = localVariableTableParameterNameDiscoverer.getParameterNames(targetMethod);
                
                //遍历方法名称列表
                int i = 0;
                for (String parameter: parameterNames) {
                    if (parameter.equals(key)) {
                        //找到指定名称的参数
                        arg = args[i];
                    }
                    i++;
                }

            }
        }

        // 每次都会正常执行原本方法逻辑，并且删除缓存
        Object proceed = null;
        Object[] args = point.getArgs();
        try {
            proceed = point.proceed(args);
            if (cache != null && arg != null) {
                cache.evict(arg);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}
